/*
* Copyright (c) 2005 MonkeyWorld3d - Monkey World 3d
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in the
*    documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Monkey World 3d, MW3D, MonkeyWorld3d, nor the
*    names of its contributors may be used to endorse or promote products derived
*    from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.trussell.genesis.editor;

import com.jme.math.FastMath;
import com.jme.math.Vector2f;
import com.jme.math.Vector3f;
import com.jme.renderer.ColorRGBA;
import com.jme.scene.TexCoords;
import com.jme.scene.TriMesh;
import com.jme.util.geom.BufferUtils;
import com.jmex.terrain.TerrainBlock;

/**
 * This is a class which will be used to mark the terrain cursor position.
 * I will try to create a circle with some radius.
 * 
 * @author ndebruyn
 * Created on May 31, 2005
 */
public class TerrainMarker extends TriMesh {

   private static final long serialVersionUID = 1L;
   private int radialSamples;
   private float radius;
   private float ringWidth;
   private ColorRGBA colorRGBA;
   private Vector3f[] vertex;
   private Vector3f[] normal;
   private ColorRGBA[] color;
   private Vector2f[][] texture;
   private int[] indices;


   public TerrainMarker(String name, int radialSamples, float radius, float ringWidth, ColorRGBA colorRGBA) {
      super(name);

      this.radialSamples = radialSamples;
      this.radius = radius;
      this.ringWidth = ringWidth;
      this.colorRGBA = colorRGBA;

      texture = new Vector2f[1][];
      // allocate vertices
      int quantity = ((radialSamples+1) * 2);
      vertex = new Vector3f[quantity];
      normal = new Vector3f[quantity];
      color = new ColorRGBA[quantity];
      texture[0] = new Vector2f[quantity];
      
      int indexQuantity = radialSamples * (6);
      indices = new int[indexQuantity];

      setGeometryData();
      setColorData();
      setIndexData();
      this.setLightCombineMode(LightCombineMode.Off);
      this.setTextureCombineMode(TextureCombineMode.Off);
      
      this.setMode(Mode.Strip);
   }

   private void setGeometryData() {
      // generate geometry
      float f1 = 1.0F / (float)radialSamples;
      int c = 0;
      for (int r=0; r<radialSamples+1; r++) {
   
         float f2 = FastMath.TWO_PI * (f1 * (float)r);
         if (r == radialSamples) {
            f2 = FastMath.TWO_PI * (f1 * (float)0);
         }
         //Outsize
         float x = radius * FastMath.cos(f2);
         float z = radius * FastMath.sin(f2);
         float y = 0.0F;
         Vector3f vector3f2out = new Vector3f(x, y, z);
         
         //Insize
         x = (radius-(ringWidth)) * FastMath.cos(f2);
         z = (radius-(ringWidth)) * FastMath.sin(f2);
         y = 0.0F;
         Vector3f vector3f2in = new Vector3f(x, y, z);
         vertex[c] = vector3f2out;
         c++;
         vertex[c] = vector3f2in;
         c++;
      }       
      this.setVertexBuffer(BufferUtils.createFloatBuffer(vertex));
      this.setColorBuffer(BufferUtils.createFloatBuffer(color));
      this.setVertexBuffer(BufferUtils.createFloatBuffer(normal));
      this.setTextureCoords(new TexCoords(BufferUtils.createFloatBuffer(texture[0]), 0));
   }

   private void setIndexData() {
      // generate connectivity
       int c = 0;
       int t = 0;
      for (; t < indices.length; t=t+3) {
          indices[t] = c;
          indices[t+1] = c+1;
          indices[t+2] = c+2;
          c++;
      }
      this.setIndexBuffer(BufferUtils.createIntBuffer(indices));
   }

   private void setColorData() {
      for (int x = 0; x < color.length; x++) {
         color = color;
      }
      this.setColorBuffer(BufferUtils.createFloatBuffer(color));
   }
    
    /**
     * We need to update the marker position.
     */
    public void update(Vector3f midPoint, TerrainBlock page) {
        setLocalTranslation(midPoint);        
        float x = getLocalTranslation().x;
        float y = getLocalTranslation().y;
        float z = getLocalTranslation().z;
        float newY;
        float incrMent = 0.3F;
        float oldY = 0.0F;
        
        for (int t=0; t<vertex.length; t++) {
            newY = page.getHeight(x+vertex[t].x, z+vertex[t].z);
            //I the value is a NaN set it to be 0.0F
            if (Float.isNaN(newY) || newY > radius+y) {
                vertex[t].y = (oldY-y) + incrMent;
           } else {
                vertex[t].y = (newY-y) + incrMent;
                oldY = newY;
            }
        }
        reconstruct(vertex, normal, color, texture[0]);
        updateGeometricState(0.0F, true);
    }
    
    private void reconstruct(Vector3f[] vertex2, Vector3f[] normal2,
         ColorRGBA[] color2, Vector2f[] vector2fs) {
      // TODO Auto-generated method stub
      super.reconstruct(BufferUtils.createFloatBuffer(vertex), 
            BufferUtils.createFloatBuffer(normal), 
            BufferUtils.createFloatBuffer(color), 
            new TexCoords(BufferUtils.createFloatBuffer(texture[0]), 0));
   }

   public void reset(ColorRGBA colorRGBA, float radius) {
        if (colorRGBA != null)
            this.colorRGBA = colorRGBA;
        
        this.radius = radius;
        setGeometryData();
        setColorData();
        reconstruct(vertex, normal, color, texture[0]);
        updateGeometricState(0.0F, true);
    }
    public float getRadius() {
        return radius;
    }
}